package api

import (
	"net/http"
	"strconv"

	"github.com/emicklei/go-restful"
	restfulspec "github.com/emicklei/go-restful-openapi"

	"github.com/xdhuxc/asset-management-system/src/model"
	"github.com/xdhuxc/asset-management-system/src/pkg"
)

type transactionController struct {
	*BaseController
}

func newTransactionController(bc *BaseController) *transactionController {
	tags := []string{"ams-transaction-details"}
	tc := &transactionController{bc}

	tc.ws.Route(tc.ws.POST("/transaction").
		To(tc.Create).
		Doc("create a transaction record").
		Metadata(restfulspec.KeyOpenAPITags, tags).
		Returns(http.StatusOK, "OK", model.Result{}).
		Returns(http.StatusBadRequest, "ERROR", model.Result{}))

	tc.ws.Route(tc.ws.DELETE("/transaction/{id}").
		To(tc.Delete).
		Doc("delete a transaction record").
		Metadata(restfulspec.KeyOpenAPITags, tags).
		Param(tc.ws.PathParameter("id", "the id of transaction record").DataType("string").Required(true)).
		Returns(http.StatusOK, "OK", model.Result{}).
		Returns(http.StatusBadRequest, "ERROR", model.Result{}))

	tc.ws.Route(tc.ws.PUT("/transaction").
		To(tc.Update).
		Doc("update a transaction record").
		Metadata(restfulspec.KeyOpenAPITags, tags).
		Reads(&model.BankTransactionDetails{}).
		Returns(http.StatusOK, "OK", model.Result{}).
		Returns(http.StatusBadRequest, "ERROR", model.Result{}))

	tc.ws.Route(tc.ws.PUT("/transactions").
		To(tc.List).
		Doc("paginate transaction records").
		Metadata(restfulspec.KeyOpenAPITags, tags).
		Reads(&model.BankTransactionDetails{}).
		Returns(http.StatusOK, "OK", model.Result{}).
		Returns(http.StatusBadRequest, "ERROR", model.Result{}))

	return tc
}

func (tc *transactionController) Create(req *restful.Request, resp *restful.Response) {
	var btd model.BankTransactionDetails

	if err := req.ReadEntity(&btd); err != nil {
		pkg.WriteResponse(resp, pkg.CreateTrancactionError, err)
		return
	}

	result, err := tc.bs.TransactionService.Create(&btd)
	if err != nil {
		pkg.WriteResponse(resp, pkg.CreateTrancactionError, err)
		return
	}

	_ = resp.WriteEntity(model.NewResult(0, nil, result))
}

func (tc *transactionController) Delete(req *restful.Request, resp *restful.Response) {
	transactionID, err := strconv.ParseInt(req.PathParameter("id"), 10, 64)
	if err != nil {
		pkg.WriteResponse(resp, pkg.DeleteTransactionError, err)
		return
	}

	err = tc.bs.TransactionService.Delete(transactionID)
	if err != nil {
		pkg.WriteResponse(resp, pkg.DeleteTransactionError, err)
		return
	}

	resp.WriteHeader(http.StatusNoContent)
}

func (tc *transactionController) Update(req *restful.Request, resp *restful.Response) {
	var btd model.BankTransactionDetails
	if err := req.ReadEntity(&btd); err != nil {
		pkg.WriteResponse(resp, pkg.UpdateTransactionError, err)
		return
	}

	result, err := tc.bs.TransactionService.Update(&btd)
	if err != nil {
		pkg.WriteResponse(resp, pkg.UpdateTransactionError, err)
		return
	}

	_ = resp.WriteEntity(model.NewResult(0, nil, result))
}

func (tc *transactionController) List(req *restful.Request, resp *restful.Response) {
	page, ok := req.Attribute("page").(model.Page)
	if !ok {
		pkg.WriteResponse(resp, pkg.ListTransactionError, "the absent of parameter page")
		return
	}

	count, btds, err := tc.bs.TransactionService.List(page)
	if err != nil {
		pkg.WriteResponse(resp, pkg.ListTransactionError, err)
		return
	}

	_ = resp.WriteEntity(model.NewResult(count, &page, btds))
}
